#include <windows.h>
#include <mmsystem.h>

#include "FrameCounter.h"

#include <ezlogger_headers.hpp>

namespace Crows3D
{

   FrameCounter::FrameCounter(void)
   {
      EZLOGGERSTREAM << "Frame Counter Constructor" << std::endl;
      counter = 0;
      currentFPS = 0;
      lastSecondStartTime = 0;
      lastFrameTime = 0;

      minTime = 0xFFFFFFFF;
      maxTime = 0;


      frequency = 0;
      highPerfCounter = 0;
      lastFrameTimeHighPerf = 0;

   }

   FrameCounter::~FrameCounter(void)
   {
      EZLOGGERSTREAM << "Frame Counter Destructor" << std::endl;
   }

   bool FrameCounter::Initialize(void)
   {
      EZLOGGERSTREAM << "Creating the Frame Counter class" << std::endl;

      lastSecondStartTime = lastFrameTime = timeGetTime();


      return true;
   }

   unsigned long FrameCounter::Frame()
   {
      unsigned long delta;

      //EZLOGGERSTREAM << "Logging the time and calculating the time since the previous call" << std::endl;

      // Get the current time
      unsigned long newTime = timeGetTime();
      
      // If it has been more than a second: 
      if (newTime - lastSecondStartTime > 1000)
      {
         // Save the number of frames we counted this second
         currentFPS = counter;

         // reset the counter
         counter = 0;

         // reset to the current time
         lastSecondStartTime = newTime;
         
         // Save the max/min times
         curMinTime = minTime;
         curMaxTime = maxTime;

         // Reset the temp max/min
         minTime = 0xFFFFFFFF;
         maxTime = 0;
      }

      // Increment the counter
      counter++;
      
      // High Perf timer
      {
         __int64 temp;

         // Make sure to check frequency often, it could change!
         QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);

         // save the current time
         QueryPerformanceCounter((LARGE_INTEGER*)&temp);

         delta = (unsigned long)(((temp - lastFrameTimeHighPerf) * 1000000) / frequency);

         lastFrameTimeHighPerf = temp;

         if (delta < minTime)
         {
            minTime = delta;
         }
         else if (delta > maxTime)
         {
            maxTime = delta;
         }
      }



      return delta;
   }

   int FrameCounter::GetCurrentFPS(void)
   {
      return currentFPS;
   }

   unsigned long FrameCounter::GetCurrentMaxTime(void)
   {
      return curMaxTime;
   }

   unsigned long FrameCounter::GetCurrentMinTime(void)
   {
      return curMinTime;
   }



   bool FrameCounter::StartHighPerformanceTimer(void)
   {
      // Make sure to check often, it could change!
      QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);

      // save the current time
      BOOL result = QueryPerformanceCounter((LARGE_INTEGER*)&highPerfCounter);

      return (result ? true : false);
   }


   int FrameCounter::StopHighPerformanceTimer(void)
   {
      __int64 temp;
      int ret;

      QueryPerformanceCounter((LARGE_INTEGER*)&temp);

      //
      ret = (unsigned int)(((temp - highPerfCounter) * 1000000) / frequency);

      return ret;
   }

}